#include "whqx_mesh_service.h"
#include <stdio.h>
#include <libubus.h>
#include <libubox/uloop.h>
#include <libubox/list.h>
#include <libubox/blobmsg_json.h>
#include <cjson/cJSON.h>
#include "comm.h"
#include "data_type.h"

extern t_RunCfg runCfg;
struct blob_buf whqx_mb;

extern int mqtt_send_data(char *payload);

// 定义策略表
static const struct blobmsg_policy whqx_data_policy[] = {
    [0] = { .name = "basicData", .type = BLOBMSG_TYPE_TABLE },
    [1] = { .name = "connectlist",   .type = BLOBMSG_TYPE_ARRAY },
};

static const struct blobmsg_policy basic_whqx_data_policy[] = {
    [0] = { .name = "modelname",    .type = BLOBMSG_TYPE_STRING },
    [1] = { .name = "firversion", .type = BLOBMSG_TYPE_STRING },
    [2] = { .name = "mac", .type = BLOBMSG_TYPE_STRING },
    [3] = { .name = "runtime", .type = BLOBMSG_TYPE_STRING },
};

static const struct blobmsg_policy connect_list_policy[] = {
    [0] = { .name = "mac",    .type = BLOBMSG_TYPE_STRING },
    [1] = { .name = "expect", .type = BLOBMSG_TYPE_STRING },
    [2] = { .name = "ssid", .type = BLOBMSG_TYPE_STRING },
    [3] = { .name = "noise", .type = BLOBMSG_TYPE_STRING },
    [4] = { .name = "rxbit", .type = BLOBMSG_TYPE_STRING },
    [5] = { .name = "acktimeout", .type = BLOBMSG_TYPE_STRING },
    [6] = { .name = "txbit", .type = BLOBMSG_TYPE_STRING },
    [7] = { .name = "signal", .type = BLOBMSG_TYPE_STRING },
};

static void ubus_whqx_callback(struct ubus_request *req, int type, struct blob_attr *msg) {
    if (!msg) return;
    
    struct blob_attr *tb[2];
    blobmsg_parse(whqx_data_policy, ARRAY_SIZE(whqx_data_policy), tb, blob_data(msg), blob_len(msg));



    uint8_t modelNumber[50]={0};
    cJSON *root = cJSON_CreateObject();

    EP_JSON_SET_STR(root, "sn", runCfg.sn);
    EP_JSON_SET_INT(root, "dataType", 2);
    EP_JSON_SET_INT(root, "version", 1);

    cJSON *meshData = cJSON_CreateObject();
    sprintf(modelNumber, "%s_MESH_1", runCfg.sn);
    EP_JSON_SET_STR(meshData, "modelNumber", modelNumber);
    cJSON *staticData = cJSON_CreateObject();

    if (tb[0]) {
        struct blob_attr *tb_basic[4];
        blobmsg_parse(basic_whqx_data_policy, ARRAY_SIZE(basic_whqx_data_policy), tb_basic, blobmsg_data(tb[0]), blobmsg_data_len(tb[0]));
        if(tb_basic[0]){
            EP_JSON_SET_STR(staticData, "modelname", blobmsg_get_string(tb_basic[0]));
        }
        if(tb_basic[1]){
            EP_JSON_SET_STR(staticData, "softwareVersion", blobmsg_get_string(tb_basic[1]));
        }
        if(tb_basic[2]){
            EP_JSON_SET_STR(staticData, "mac", blobmsg_get_string(tb_basic[2]));
        }
        if(tb_basic[3]){
            EP_JSON_SET_STR(staticData, "runningTime", blobmsg_get_string(tb_basic[3]));
        }
        cJSON_AddItemToObject(meshData,"staticData",staticData);
    }

    if (tb[1]) {
        
        struct blob_attr *connectlist;
        size_t rem;
        cJSON *array = cJSON_CreateArray();
        blobmsg_for_each_attr(connectlist, tb[1], rem) {
            struct blob_attr *tb_remote[8];
            blobmsg_parse(connect_list_policy, ARRAY_SIZE(connect_list_policy), tb_remote,
                      blobmsg_data(connectlist), blobmsg_data_len(connectlist));
            cJSON *remote = cJSON_CreateObject();
            if (tb_remote[0]) {
                EP_JSON_SET_STR(remote, "mac", blobmsg_get_string(tb_remote[0]));
            }
            if (tb_remote[1]) {
                EP_JSON_SET_STR(remote, "expect", blobmsg_get_string(tb_remote[1]));
            }
            if (tb_remote[2]) {
                EP_JSON_SET_STR(remote, "ssid", blobmsg_get_string(tb_remote[2]));
            }
            if (tb_remote[3]) {
                EP_JSON_SET_STR(remote, "noise", blobmsg_get_string(tb_remote[3]));
            }
            if (tb_remote[4]) {
                EP_JSON_SET_STR(remote, "rxbit", blobmsg_get_string(tb_remote[4]));
            }
            if (tb_remote[5]) {
                EP_JSON_SET_STR(remote, "acktimeout", blobmsg_get_string(tb_remote[5]));
            }
            if (tb_remote[6]) {
                EP_JSON_SET_STR(remote, "txbit", blobmsg_get_string(tb_remote[6]));
            }
            if (tb_remote[7]) {
                EP_JSON_SET_STR(remote, "signal", blobmsg_get_string(tb_remote[7]));
            }
            cJSON_AddItemToArray(array, remote);
        }
        cJSON_AddItemToObject(meshData,"connectionData",array);
    }

    cJSON_AddItemToObject(root,"data",meshData);
    char *str = cJSON_Print(root);
    printf("%s\n", str);
    mqtt_send_data(str);
    cJSON_Delete(root);
}

int read_whqx_status_data() {
    struct ubus_context *ctx = ubus_connect(NULL);
    if (!ctx) {
        fprintf(stderr, "ubus connect failed\n");
        return -1;
    }
    uint32_t obj_id;
    if (ubus_lookup_id(ctx, "sihan.mesh.whqx", &obj_id) != 0) {
        fprintf(stderr, "lookup failed\n");
        ubus_free(ctx);
        return -1;
    }
    
    blob_buf_init(&whqx_mb, 0);
    //设置参数，如：{"action":"status"}
    // blobmsg_add_string(&b, "action", "status");
    
    // 需要事件循环（此处简化为等待）
    if (ubus_invoke(ctx, obj_id, "info", whqx_mb.head, ubus_whqx_callback, NULL, 3000) != 0) {
        fprintf(stderr, "invoke failed\n");
    }

    blob_buf_free(&whqx_mb);
    ubus_free(ctx);
    return 0;
}

//接收LoRa数据的线程
void *whqx_mesh_worker(void *param)
{
    while (1)
    {
        read_whqx_status_data();
        sleep(5 * 60);
    }
}

int whqx_mesh_worker_start() {
    if(runCfg.mesh_enable){
        pthread_t pid;
        pthread_create(&pid, NULL, (void *)whqx_mesh_worker, NULL);
    }
}